#include <linux/platform_device.h>
#include <linux/module.h>
#include <linux/kdev_t.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include "interface.h"

static int maj_no = 250;
static int mi_no = 0;
static char devname[] = "photosensor_dev";
static const int count = 1;
static int number;
static const int baseminor = 0;
static struct cdev *pdev;
static struct class *pclass;
static unsigned int *pcon=NULL;
static unsigned int *pdata = NULL;
MODULE_LICENSE("GPL");
MODULE_AUTHOR("ZHANG SAN");
MODULE_DESCRIPTION("A TEST MODULE, EMPTY");


int photosensorOpen( struct inode *p,  struct file *f)
{
	//printk("hahaha device open\n");
	return 0;
}

int photosensorClose( struct inode *p,  struct file *f)
{
	//printk("photosensor device close\n");
	return 0;
}
long photosensorIoctl(struct file *f, unsigned int cmd,  unsigned long arg)
{
	unsigned int tmp;
	int i;
	switch(cmd)
	{
		case LIGHT_L:
			
			tmp = ioread32(pdata);
			if((1 << 3) & tmp)
			{
				i = 1;
				return i; 
			}else 
			{
				i=0;
				return i;
			}
	}
	return 0;
}
struct file_operations photosensorOPS =
{
	.owner = THIS_MODULE,

	
	.open = photosensorOpen,
	.release = photosensorClose,
	.unlocked_ioctl = photosensorIoctl,
};


int photosensorDriverProbe(struct platform_device *pDevice)
{
	struct resource *res = pDevice->resource;
	int i;
	struct device *pdevice;
	unsigned int tmp;

	pcon = ioremap(res[0].start,4);
	pdata = ioremap(res[1].start,4);
	tmp = ioread32(pcon);
	tmp = tmp & ~(0xf << 12);
	iowrite32(tmp, pcon);

	
	
	if(alloc_chrdev_region(&number,baseminor,count, devname))
	{
	//	printk("number register faild\n");
		return -1;
	}	 
	maj_no = MAJOR(number);
	pdev = cdev_alloc();
	if( NULL == pdev)
		goto CDEV_ALLOC_ERR;
	cdev_init(pdev, &photosensorOPS);
	if(cdev_add(pdev, number,count))
		goto CDEV_ADD_ERR;
	pclass = class_create(THIS_MODULE,"photosensor");
	if(IS_ERR(pclass))
		goto CLASS_CREATE_ERR;
	for(i = 0; i < 1; i++)
	{
		pdevice = device_create(pclass, 0,MKDEV(maj_no,i),0, "photosensor_dev");
		if(IS_ERR(pdevice))
			goto DEVICE_CREATE_ERR;	

	}
    //    printk("HelloDriverProbe\r\n");
	
	return 0;
DEVICE_CREATE_ERR:
	class_destroy(pclass);
CLASS_CREATE_ERR:
CDEV_ADD_ERR:
	cdev_del(pdev);
CDEV_ALLOC_ERR:
	unregister_chrdev_region(number, count);
	return -1;
	
}

int photosensorDriverRemove(struct platform_device *pDevice)
{
	int i;
	iounmap(pcon);
	iounmap(pdata);
	for(i = 0; i < count; i++)
		device_destroy(pclass, MKDEV(maj_no, i));
	class_destroy(pclass);
	cdev_del(pdev);
	unregister_chrdev_region(number,count);
	//printk("exit module, cleanup_module\n");

       // printk("photosensorDriverRemove\r\n");
        return 0;
}


static struct platform_driver g_stPlantFormDriver =
{
        .driver = {
                .name = "photosensor_dev",
                .owner = THIS_MODULE,
        },
        .probe  = photosensorDriverProbe,
        .remove =  photosensorDriverRemove,
};


int photosensorInit(void)
{
        int iRet = 0;
     //  printk("driver,  module init enter\r\n");

        iRet = platform_driver_register(&g_stPlantFormDriver);
        if (0 != iRet)
        {
               // printk("platform_driver_register error");
		return -1;
        }
        printk("driver,  module init exit\r\n");
        return iRet;

}

void photosensorRelease(void)
{
        printk("driver,  clean module enter\r\n");
        platform_driver_unregister(&g_stPlantFormDriver);
        printk("driver,   clean module exit\r\n");
}

module_exit(photosensorRelease);
module_init(photosensorInit);

MODULE_LICENSE("GPL");


